home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
tex
/
uniq.zip
/
UNIQ.C
< prev
next >
Wrap
C/C++ Source or Header
|
1994-05-23
|
5KB
|
224 lines
/* UNIX uniq text utility for MS-DOS
*
* uniq - remove or report adjacent duplicate lines
*
* Usage: uniq [ -cdu ] [ +|-n ] [ inputfile [ outputfile ] ]
*
* uniq version 1.1, 23-May-94 by Jason Mathews
*
* Copyright (C) 1992-94 by Jason Mathews. Permission is granted to any
* individual or institution to use, copy or redistribute this software so long
* as it is not sold for profit, provided this copyright notice is retained.
*
* Modification history:
*
* V1.0 23-Nov-92 Original version (clone of the UNIX uniq command)
* Compiled and tested with Borland C++ V3.1 compiler.
* V1.1 23-May-94 Fixed skip field/character processing.
****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_STRING_LEN 1024
#define whitespace(c) ((c)==' ' || (c)=='\t')
/* define alternate switch for non-unix systems */
#ifdef unix
# define ALT_SW
#else
# define ALT_SW **argv=='/' ||
#endif
typedef unsigned char Bool;
typedef unsigned char UChar;
typedef char String[MAX_STRING_LEN];
enum { DEFAULT=0, DUPS, COUNT_LINES, NOREPEATS };
/* input buffer for the current and previous input lines */
String buffer[2] = { "", "" };
int numFields = 0;
int indent = 0;
Bool newbuf = 0; /* buffer index toggles between 1 and 0 */
Bool showCount = 0;
int count = 0;
UChar mode = DEFAULT;
/* Function prototypes */
char* fgetline(char *s, int n, FILE *fp);
void CheckState(char *s);
int CheckLine(void);
int main (int argc, char **argv)
{
Bool gotFirstLine = 0; /* flag indicating we have stored the first line */
char *filename;
/* skip over 0 argument and increment through arg-list */
while (*(++argv))
{
if (ALT_SW **argv == '-')
{
switch (*(++*argv)) {
case 'd': /* write one copy of repeated lines */
mode = DUPS;
break;
case 'c': /* Precede each line with a count of the number of times it occured */
mode = COUNT_LINES;
break;
case 'u': /* copy only lines not repeated in the orginal file */
mode = NOREPEATS;
break;
case 'h':
case '?':
fprintf(stderr,
"uniq (C) 1992-94 Jason Mathews\n\n"
"Usage: uniq [ -cdu ] [ +|-n ] [ inputfile [ outputfile ] ]\n"
" -c Precede each line with a count of the number of times it occurred\n"
" -d Write one copy of duplicate lines\n"
" -u Copy only lines not repeated in the orginal file\n"
" +n Skips over the first n characters\n"
" -n Skips over the first n fields\n");
return 0;
default:
if (*(*argv-1) != '/')
{
numFields = atoi(*argv);
if (numFields < 0) numFields = 0;
}
} /* switch */
}
else if (**argv == '+')
{
indent = atoi(*argv+1);
if (indent < 0) indent = 0;
}
else break;
} /* while */
if (*argv != NULL)
{
filename = *argv++;
/* redirect stdin to file */
if (freopen (filename, "r", stdin) == 0)
{
fprintf(stderr, "uniq: cannot open %s\n", filename);
return 1;
}
}
if (*argv != NULL)
{
filename = *argv++;
/* redirect stdout to file */
if (freopen( filename, "w", stdout ) == 0)
{
fprintf(stderr, "uniq: cannot create %s\n", filename);
return 1;
}
}
while (fgetline(buffer[newbuf], MAX_STRING_LEN, stdin))
{
if (gotFirstLine != 0) /* do we have two lines to compare? */
{
if (CheckLine()) count++; /* if duplicate */
else
{
CheckState( buffer[newbuf] );
count = 1; /* reset counter */
}
}
else
{
gotFirstLine = 1;
count = 1;
newbuf = !newbuf; /* toggle buffer to next location */
}
} /* while */
/* check last input line */
if (gotFirstLine)
{
CheckState( buffer[!newbuf] );
}
return 0;
} /* end main */
/*
* fgetline - get line from file
*/
char* fgetline (char *s, int n, FILE *fp)
{
register int c;
register char *P = s;
/* read until the end of line or the end of file is reached */
while (((c = getc(fp)) != '\n') && c != EOF)
{
if (--n > 0) *P++ = c;
}
if (EOF == c && P == s) return( NULL );
*P = 0;
return (ferror (fp)) ? NULL : s;
}
/*
* Adjust - adjust line for specified fields/characters
*/
char* Adjust( char *s )
{
int count = 0;
/* ignore first n fields */
while (*s && count++ < numFields)
{
while (whitespace(*s)) s++;
while (*s && !whitespace(*s)) s++;
}
count = indent;
/* ignore first n characters */
while (count != 0 && *s != 0)
{
s++;
count--;
}
return s;
}
/*
* CheckLine - check and parse current input line
*
* Returns: 1 if line matches previous line, 0 otherwise.
*/
int CheckLine ()
{
char *s1 = Adjust(buffer[newbuf]);
char *s2 = Adjust(buffer[!newbuf]);
/* duplicate string? */
if (!strcmp(s1, s2)) return 1;
newbuf = !newbuf; /* toggle buffer to next location */
return 0; /* unique line */
} /* end CheckLine */
/*
* CheckState - print line if appropriate to selected mode
*/
void CheckState (char *s)
{
if (mode == COUNT_LINES) printf("%4d %s\n", count, s);
else
{
if (mode==DEFAULT || mode==NOREPEATS && count==1 ||
mode==DUPS && count > 1)
printf("%s\n", s);
}
}